-- $Id: $
-- File name:   InBlock.vhd
-- Created:     4/3/2011
-- Author:      Brandon Davis
-- Lab Section: 337-06
-- Version:     1.0  Initial Design Entry
-- Description: Audio Input Block


LIBRARY IEEE;
USE IEEE.std_logic_1164.ALL;
USE IEEE.STD_LOGIC_ARITH.All;
USE IEEE.STD_LOGIC_UNSIGNED.All;

entity InBlock is
  port(RST, BCLK, EN, SYNC, STRB: in std_logic;
    DataReadyB, DataReadyW, Shift1En, Shift2En, ZeroPad: out std_logic);
end InBlock;

architecture A_InBlock of InBlock is
  type state_type is (Init, Hold, Hold2, Resp, Resp2, Resp3, RespClean, DataRec, DataRec2, Clean);
  type state2_type is (Idle, Write, WriteB);
  signal state, nextState : state_type;
  signal state2, nextState2 : state2_type;
  signal bitCount, nextBitCount : std_logic_vector(7 downto 0);
  signal wordCount, nextWordCount: std_logic_vector(4 downto 0);
  signal genCount, nextGenCount : std_logic_vector(3 downto 0);
  
  
  Begin
  StateReg:process(EN, RST, BCLK)
  Begin
    if (RST = '0') then
      bitCount <= x"00";
      wordCount <= "00000";
      genCount <= x"0";
      state <= Init;
      state2 <= Idle;
    elsif (EN = '0') then
      bitCount <= x"00";
      wordCount <= "00000";
      genCount <= x"0";
      state <= Init;
      state2 <= Idle;
    elsif rising_edge(BCLK) then
      state <= nextState;
      state2 <= nextState2;
      bitCount <= nextBitCount;
      wordCount <= nextWordCount;
      genCount <= nextGenCount;
    end if;
  end process StateReg;
  
  
  Next_State:process(state, bitCount, wordCount, genCount, EN, SYNC)
  Begin
    nextState <= Init;
    nextBitCount <= bitCount;
    nextWordCount <= wordCount;
    nextGenCount <= genCount;
    --Shift1En <= '0';
    --Shift2En <= '0';
    --ZeroPad <= '0';
    case state is
      when Init =>
        Shift1En <= '0';
        Shift2En <= '0';  --Recently Added (Modification seems to work well)
        ZeroPad <= '0';
        if (EN = '1' and SYNC = '1') then
          nextState <= Hold;
        end if;
        
      when Hold =>
        if (genCount = x"2") then
          nextState <= Resp;
          nextGenCount <= x"0";
        else
          nextGenCount <= genCount + 1;
          nextState <= Hold;
        end if;
        
      when Resp =>
        Shift1En <= '1';
        Shift2En <= '0';
        ZeroPad <= '0';
        nextBitCount <= bitCount + 1;
        if (bitCount = x"0F") then --15
          nextState <= Resp2;
          nextWordCount <= wordCount + 1;
        else
          nextState <= Resp;
        end if;
        
      when Resp2 =>
        Shift2En <= '1';
        Shift1En <= '0';
        nextBitCount <= bitCount + 1;
        if (bitCount = x"1F") then --31
          nextState <= Resp3;
          nextWordCount <= wordCount + 1;
        else
          nextState <= Resp2;
        end if;
        
      when Resp3 =>
        Shift1En <= '1';
        Shift2En <= '0';
        nextBitCount <= bitCount + 1;
        if (bitCount = x"23") then --35
          nextState <= RespClean;
        else
          nextState <= Resp3;
        end if;
        
      when RespClean =>
        Shift1En <= '1';
        Shift2En <= '0';
        ZeroPad <= '1';
        nextBitCount <= bitCount + 1;
        if (bitCount = x"27") then --39
          nextState <= Hold2;
        else
          nextState <= RespClean;
        end if;
        
      when Hold2 =>
        Shift2En <= '1';
        Shift1En <= '0';
        ZeroPad <= '0';
        if (genCount = x"5") then --5
          nextState <= DataRec;
          nextGenCount <= x"0";
          nextBitCount <= x"00";
        else
          nextGenCount <= genCount + 1;
          nextWordCount <= "00000";
          nextBitCount <= x"00";
          nextState <= Hold2;
        end if;
        
      when DataRec =>
        Shift2En <= '1';
        Shift1En <= '0';
        if (bitCount = x"0F") then --15
          nextState <= DataRec2;
          nextWordCount <= wordCount + 1;
          nextBitCount <= x"00";
        elsif (wordCount = x"18") then --24
          nextState <= Clean;
          nextWordCount <= "00000";
          nextBitCount <= x"00";
        else
          nextBitCount <= bitCount + 1;
          nextState <= DataRec;
        end if;
        
      when DataRec2 =>
        Shift1En <= '1';
        Shift2En <= '0';
        if (bitCount = x"0F") then --15
          nextState <= DataRec;
          nextWordCount <= wordCount + 1;
          nextBitCount <= x"00";
        elsif (wordCount = x"18") then --24
          nextState <= Clean;
          nextWordCount <= "00000";
          nextBitCount <= x"00";
        else
          nextBitCount <= bitCount + 1;
          nextState <= DataRec2;
        end if;
        
      when Clean =>
        Shift2En <= '1';   --Needs looking into which one needs enabling, should be correct though.
        Shift1En <= '0';
        nextState <= Init;
      end case;
    end process Next_State;
    
    
    Ready_States:process(state2, bitcount, wordCount, nextWordCount, STRB)
    Begin
      nextState2 <= Idle;
      DataReadyW <= '0';
      DataReadyB <= '0';
      case state2 is
        when Idle =>
          if (state = Resp2 and bitCount = x"10") then
            nextState2 <= Write;
          elsif (state = Resp3 and bitCount = x"20") then
            nextState2 <= Write;
          elsif (state = Hold2 and bitCount = x"28") then
            nextState2 <= WriteB;
          elsif ((state = DataRec or state = DataRec2) and wordCount /= nextWordCount) then
            nextState2 <= Write;
          end if;
          
        when Write =>
          DataReadyW <= '1';
          if (STRB = '1') then
            nextState2 <= Idle;
          else
            nextState2 <= Write;
          end if;
          
        when WriteB =>
          DataReadyB <= '1';
          if (STRB = '1') then
            nextState2 <= Idle;
          else
            nextState2 <= WriteB;
          end if;
      end case;
    end process Ready_States;
    
end A_InBlock;
          
        
          
        
          
        
  
  
  
  
  
  
  
  
  
  
  
